package com.clp.inflxudb.spring;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

class StringUtil {
    /**
     * 将 [separator]{} 格式的占位符用实际值代替
     * @param str：要处理的字符串
     * @param strObjs：键值对对象 键为占位符名称，值为要代替的值（通过toString()）
     * @param separator：分隔符，如 # 、$
     * @return
     */
    static String replacePlaceholderByMap(String str, Map<String, Object> strObjs, char separator) {
        char[] chars = str.toCharArray();

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < chars.length;) {
            if (chars[i] != separator) {
                sb.append(chars[i]);
                i += 1;
                continue;
            }
            // chars[i] == '#'
            i += 1;

            int j = i;
            while (j < chars.length) {
                if (chars[j] == ' ') {
                    j += 1;
                    continue;
                }
                if (chars[j] != '{') throw new RuntimeException("非法字符");
                j += 1;

                int k = j;
                StringBuilder paramSb = new StringBuilder();
                while (k < chars.length) {
                    if (chars[k] == '}') {
                        k += 1;
                        break;
                    }
                    paramSb.append(chars[k]);
                    k += 1;
                }

                String paramStr = paramSb.toString();
                if (strObjs.containsKey(paramStr)) {
                    Object obj = strObjs.get(paramStr);
                    if (obj != null) {
                        sb.append(obj);
                    }
                } else {
                    sb.append(separator + "{" + paramSb + "}");
                }

                i = k;
                break;
            }
        }
        return sb.toString();
    }

    /**
     * 获取 ${} 格式的占位符名称
     * @param str
     * @return
     */
    static List<String> getPlaceholderNames(String str) {
        List<String> retList = new ArrayList<>();
        char[] chars = str.toCharArray();
        for (int i = 0; i < chars.length;) {
            if (chars[i] != '$') {
                i += 1;
                continue;
            }
            i += 1;

            int j = i;
            while (j < chars.length) {
                if (chars[j] == ' ') {
                    j += 1;
                    continue;
                }
                if (chars[j] != '{') throw new RuntimeException("非法字符");
                j += 1;

                int k = j;
                StringBuilder paramSb = new StringBuilder();
                while (k < chars.length) {
                    if (chars[k] == '}') {
                        k += 1;
                        break;
                    }
                    paramSb.append(chars[k]);
                    k += 1;
                }

                retList.add(paramSb.toString());
                i = k;
                break;
            }
        }
        return retList;
    }

    /**
     * 找到多层嵌套map的多层表示的键（如a.b.c.d）对应的值
     * @param map：多层嵌套map
     * @param keyStr：多层表示的键
     * @return
     */
    static String findValInMaps(Map<String, Object> map, String keyStr) {
        String[] keyLevel = keyStr.split("\\.");
        for (int i = 0; i < keyLevel.length - 1; i++) {
            map = getMapValue(map, keyLevel[i], Map.class);
        }
        return getMapValue(map, keyLevel[keyLevel.length - 1], String.class);
    }

    /**
     * 处理字符串，将字符串中的 [separator]{} 占位符 在 map中检索对应值并取代占位符，返回处理后的字符串
     * @param str：处理前的字符串
     * @param separator：分隔符，如 #、$
     * @param map：要检索的值所在map
     * @return
     */
    static String handlerPlaceHolder(String str, char separator, Map<String, Object> map) {
        List<String> placeholderNames = getPlaceholderNames(str);
        if (placeholderNames.isEmpty()) return str;

        Map<String, Object> strObjs = new HashMap<>();
        for (String placeholderName : placeholderNames) {
            strObjs.put(placeholderName, findValInMaps(map, placeholderName));
        }
        return replacePlaceholderByMap(str, strObjs, separator);
    }

    /**
     * 获取map的值（指定类型）
     * @param map
     * @param key
     * @param clazz
     * @param <T>
     * @return
     */
    @SuppressWarnings({"unchecked"})
    static <T> T getMapValue(Map map, String key, Class<T> clazz) {
        Object val = map.get(key);
        if (clazz.isAssignableFrom(val.getClass())) {
            return (T) val;
        } else {
            throw new RuntimeException("map值类型不正确！");
        }
    }

    static boolean strContainsChar(String str, char ch) {
        for (char c : str.toCharArray()) {
            if (c == ch) {
                return true;
            }
        }
        return false;
    }
}
